#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Provides various functionality to tack scripts
"""

import re
import textwrap

class CodeGeneratorBackend(object):
    """
    Helper class to assist in generating python code.
    Gleaned largely mostly from the code found here:
    http://effbot.org/zone/python-code-generator.htm

    >>> c = CodeGeneratorBackend()
    >>> c.indent()
    >>> c.write('import tack')
    >>> c.dedent()
    >>> c.write('sys.exit()')
    >>> c.output()
    '    import tack\\nsys.exit()\\n'

    >>> c = CodeGeneratorBackend()
    >>> c.dedent()
    Traceback (most recent call last):
        ...
    SyntaxError: internal error in code generator
    """

    def __init__(self, tab="    "):
        self.code = []
        self.tab = tab
        self.level = 0

    def output(self):
        return "".join(self.code)

    def write(self, code=""):
        self.code.append(self.tab * self.level + code + '\n')

    def indent(self):
        self.level = self.level + 1

    def current_indent(self):
        return self.tab * self.level

    def dedent(self):
        if self.level == 0:
            raise SyntaxError, "internal error in code generator"
        self.level = self.level - 1



class Pluralize(object):
    """
    Pluralizes a word.  Adapted from:
    http://www.diveintopython.org/dynamic_functions/stage5.html
    Won't catch irregular (goose - > geese, etc) plurals, of course.

    >>> p = Pluralize()
    >>> p('driver')
    'drivers'
    >>> p('church')
    'churches'
    >>> p('ax')
    'axes'
    >>> p('lily')
    'lilies'

    """

    patterns = (
        ('[sxz]$', '$','es'),
        ('[^aeioudgkprt]h$', '$', 'es'),
        ('[^aeiou]y$', 'y$', 'ies'),
        ('$', '$', 's'),
        )

    def __init__(self):
        self.rules = [self.make_pattern(pattern, search, replace)
                      for (pattern, search, replace) in Pluralize.patterns]

    def make_pattern(self, pattern, search, replace):
        return (lambda word: re.search(pattern, word)
                and re.sub(search, replace, word))

    def __call__(self, noun):
        for rule in self.rules:
            result = rule(noun)
            if result:
                return result

def wrap(s, indent = ''):
    """
    Wraps lines. Can take a string, or list of strings
    Returns one newline delimited string
    """
    wrapper = textwrap.TextWrapper(width=74)
    wrapped_s = []

    if type(s) == str:
        s = [s]

    for line in s:
        wrapped_s.append(("\n" + indent).join(wrapper.wrap(line)))

    return ("\n" + indent).join(wrapped_s)
